package dao

import (
	"context"
	"encoding/json"
	"gitee.com/xiao_hange/go-admin-log/log/domain"
	"github.com/olivere/elastic/v7"
	"strings"
	"time"
)

type Log struct {
	Index     string    `json:"index"`
	Message   string    `json:"message"`
	Timestamp time.Time `json:"@timestamp"`
}

type LogDAO interface {
	Input(ctx context.Context, log Log) error
	Search(ctx context.Context, index string, page, limit int) ([]Log, int, error)
}

type logElasticDAO struct {
	client *elastic.Client
}

func NewLogElasticDAO(client *elastic.Client) LogDAO {
	return &logElasticDAO{
		client: client,
	}
}

func (l *logElasticDAO) Input(ctx context.Context, log Log) error {
	now := time.Now()
	log.Timestamp = now
	c := l.client.Index().Index(log.Index).Id("")
	switch log.Index {
	case domain.GormLogIndex:
		log.Message = l.formatGormData(log.Message)
	default:

	}
	_, err := c.BodyJson(log).Do(ctx)
	return err
}

func (l *logElasticDAO) Search(ctx context.Context, index string, page, limit int) ([]Log, int, error) {
	from := page * limit
	resp, err := l.client.Search(index).From(from).Size(limit).Sort("@timestamp", false).Do(ctx)
	if err != nil {
		return nil, 0, err
	}
	var logs []Log
	for _, hit := range resp.Hits.Hits {
		var log Log
		log.Index = index
		_ = json.Unmarshal(hit.Source, &log)
		logs = append(logs, log)
	}
	return logs, int(resp.TotalHits()), nil
}

func (l *logElasticDAO) formatGormData(data string) string {
	start := strings.Index(data, "{")
	end := strings.LastIndex(data, "}")
	newData := data[start : end+1]
	var gorm Gorm
	var gormInfo GormInfo
	_ = json.Unmarshal([]byte(newData), &gorm)
	parts := strings.Split(gorm.GormInfo, "|")
	for _, part := range parts {
		fields := strings.SplitN(part, ":", 2)
		if len(fields) == 2 {
			fieldName := strings.TrimSpace(fields[0])
			fieldValue := strings.TrimSpace(fields[1])
			switch fieldName {
			case "ExecutionTime":
				gormInfo.ExecutionTime = fieldValue
			case "Position":
				gormInfo.Position = fieldValue
			case "Duration":
				gormInfo.Duration = fieldValue
			case "SQL":
				gormInfo.SQL = fieldValue
			case "Rows":
				gormInfo.Rows = fieldValue
			case "IsSlow":
				gormInfo.IsSlow = fieldValue
			}
		}
	}
	jsonData, _ := json.Marshal(gormInfo)
	return string(jsonData)
}

type Gorm struct {
	GormInfo string `json:"Gorm-Info"`
}

type GormInfo struct {
	ExecutionTime string
	Position      string
	Duration      string
	SQL           string
	Rows          string
	IsSlow        string
}
